Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / libcc.ansi / misc / putenv.c
1 /*
2  * (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: putenv.c,v 1.6 1994/06/24 11:45:38 ceriel Exp $ */
6
7 #include        <stdlib.h>
8 #include        <string.h>
9
10 #define ENTRY_INC       10
11 #define rounded(x)      (((x / ENTRY_INC) + 1) * ENTRY_INC)
12
13 extern const char **_penvp;
14 extern const char **environ;    /* environ is a shadow name for _penvp */
15
16 int
17 putenv(char *name)
18 {
19         register const char **v = _penvp;
20         register char *r;
21         static int size = 0;
22         /* When size != 0, it contains the number of entries in the
23          * table (including the final NULL pointer). This means that the
24          * last non-null entry  is _penvp[size - 2].
25          */
26
27         if (!name) return 0;
28         if (r = strchr(name, '=')) {
29                 register const char *p, *q;
30
31                 *r = '\0';
32
33                 if (v != NULL) {
34                         while ((p = *v) != NULL) {
35                                 q = name;
36                                 while (*q && (*q++ == *p++))
37                                         /* EMPTY */ ;
38                                 if (*q || (*p != '=')) {
39                                         v++;
40                                 } else {
41                                         /* The name was already in the
42                                          * environment.
43                                          */
44                                         *r = '=';
45                                         *v = name;
46                                         return 0;
47                                 }
48                         }
49                 }
50                 *r = '=';
51                 v = _penvp;
52         }
53
54         if (!size) {
55                 register const char **p;
56                 register int i = 0;
57
58                 if (v)
59                         do {
60                                 i++;
61                         } while (*v++);
62                 if (!(v = malloc(rounded(i) * sizeof(char **))))
63                         return 1;
64                 size = i;
65                 p = _penvp;
66                 _penvp = v;
67                 while (*v++ = *p++);            /* copy the environment */
68                 v = _penvp;
69         } else if (!(size % ENTRY_INC)) {
70                 if (!(v = realloc(_penvp, rounded(size) * sizeof(char **))))
71                         return 1;
72                 _penvp = v;
73         }
74         v[size - 1] = name;
75         v[size] = NULL;
76         size++;
77         environ = _penvp;
78         return 0;
79 }